﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PKTools.Scheduler;
using PKTools.Database;
using PKTools;

namespace Scheduler
{
    enum JobStepType
    {
        Query = 2,
        SnapShotQuery = 4,
        StoredProcedure = 8
    }

    partial class JobTask : ITask
    {
        public IJobStep GetJobStep()
        {
            return this.JobStep;
        }

        public void Create()
        {
            Sql.Context.Insert(this);
        }

        public void DeleteTask()
        {
            Sql.Context.Delete(this);
        }

        public void Execute()
        {
            DatabaseExecutor
                executor = null;

            using (var sql = new MsSql())
                switch ((JobStepType)this.JobStep.JobStepType)
                {
                    case JobStepType.Query:
                        executor = new QueryExecutor(this.JobStep);
                        break;
                }

            if (executor == null)
                throw new Exception("job type not supported");

            executor.Execute();
        }

        public void Success(DateTime currentTime)
        {
            this.Executing = false;
            Sql.Context.Update(this);

            this.JobStep.LastSuccessfulRun = currentTime;
            Sql.Context.Update(this.JobStep);

            var
                jobStepHistory = new JobStepHistory
                {
                    JobHistoryID = this.JobStep.Job.LastJobHistoryID.Value,
                    JobStepID = this.JobStepID,
                    EET = this.EET,
                    ET = currentTime,
                    IsSuccess = true
                };

            Sql.Context.Insert(jobStepHistory);
        }

        public void Fail(DateTime currentTime, Exception ex)
        {
            this.Executing = false;
            Sql.Context.Update(this);

            var
                jobStepHistory = new JobStepHistory
                {
                    JobHistoryID = this.JobStep.Job.LastJobHistoryID.Value,
                    JobStepID = this.JobStepID,
                    EET = this.EET,
                    ET = currentTime,
                    IsSuccess = false,
                    ErrorCode = ex.Message
                };

            Sql.Context.Insert(jobStepHistory);
        }

        public bool CanRetry()
        {
            return this.Attempts < this.Retries;
        }

        public void Retry(Exception ex)
        {
            var
                t = this.EET.AddSeconds(this.JobStep.RetryDelay);

            Log.Entry(LogSeverity.Info, "retry EET {0} > {1}", this.EET.ToDetailString(), t.ToDetailString());

            this.EET = t;

            Sql.Context.Update(this);                        
        }

        public void FinalFail(Exception ex)
        {
            this.JobStep.Job.JobHistory_LastJobHistoryID.JobState = 6;  // completed with errors
            Sql.Context.Update(this.JobStep.Job.JobHistory_LastJobHistoryID);
        }

        public void BeforeExecution(DateTime currentTime)
        {
            ++this.Attempts;
            Sql.Context.Update(this);

            this.JobStep.LastRun = currentTime;
            Sql.Context.Update(this.JobStep);
        }

        public override string ToString()
        {
            return this.JobStepID.ToString();
        }
    }
}
